﻿using MCP.BL.Messages;
using MCP.Model.Repositories;
using System;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using MCP.Model.Repositories.Interfaces;
using client = MCP.Data.Client;
using server = MCP.Data.CF_Entities;

namespace MCP.Model.Helpers
{
	/// <summary>
	/// Extra extension methods container.
	/// </summary>
	public static class Extensions
	{
		#region Check

		public static server.Check ToServerCheck(this client.Check clientCheck)
		{
			var serverItems = new EntityCollection<server.Item>();
			foreach (var item in clientCheck.Items)
			{
				serverItems.Add(
					new server.Item()
						{
							Name = item.Name,
							Amount = item.Amount,
							Price = item.Price,
							UnitPrice = item.UnitPrice
                            //,UserID = CurrentUserHelper.UserID
						});
			}

            //server.Shop shop = null;
            //// DB connection:
            //using (var unitOfWork = new UnitOfWork())
            //{
            //    shop = unitOfWork.ShopRepository.GetShopByName(clientCheck.ShopName);
            //}

			var serverCheck = new server.Check()
								  {
									  TotalPrice = clientCheck.TotalPrice,
									  Items = serverItems,
                                      //Shop = shop,
									  Date = DateTime.Now,
									  UserID = CurrentUserHelper.UserID
								  };

			return serverCheck;
		}

        //public static server.Check ToServerCheck(this client.Check clientCheck, server.Shop shop)

		public static client.Check ToClientCheck(this server.Check serverCheck)
		{
			var clientCheck = new client.Check()
								  {
									  ID = serverCheck.ID,
									  //ShopName = serverCheck.Shop != null ? serverCheck.Shop.Name : null,
									  TotalPrice = (double)serverCheck.TotalPrice,
									  Items = serverCheck.Items
										  .Select(i => i.ToClientItem())
                                          .ToList(),
									  Date = serverCheck.Date,
									  DateOnly = serverCheck.Date.ToShortDateString(),
									  TimeOnly = serverCheck.Date.ToShortTimeString()
								  };

			return clientCheck;
		}

		public static IEnumerable<client.Check> ToClientChecks(this IEnumerable<server.Check> checks)
		{
			return checks.Select(c => c.ToClientCheck());
		}

		#endregion

        #region Items

        public static server.Item ToServerItem(this client.Item item)
        {
            return new server.Item()
                {
                    Name = item.Name,
                    Price = item.Price,
                    Amount = item.Amount,
                    UnitPrice = item.UnitPrice,
                    Categories = item.Categories
                        .Select(c => new server.Category() {CategoryName = c})
                        .ToList()
                };
        }

        public static client.Item ToClientItem(this server.Item item)
        {
            return new client.Item()
                {
                    Name = item.Name,
                    Price = item.Price ?? 0,
                    Amount = item.Amount ?? 0,
                    UnitPrice = item.UnitPrice ?? 0,
                    Categories = item.Categories.Select(c => c.CategoryName).ToList()
                };
        }

        #endregion

        #region Category

        public static client.Category ToClienCategory(this server.Category category)
		{
			return new client.Category() { ID = category.ID, Name = category.CategoryName };
		}

		public static server.Category ToServerCategory(this client.Category category)
		{
			//return category.ID != Guid.Empty
			//           ? EntityHelper.CategoryHelper.GetCategory(category.ID)
			//           : EntityHelper.CategoryHelper.GetCategory(category.Name);
			return new server.Category()
					   {
						   ID = category.ID,
						   CategoryName = category.Name
					   };
		}

		public static IEnumerable<client.Category> ToClientCategories(this IEnumerable<server.Category> categories)
		{
			return categories.Select(c => c.ToClienCategory());
		}

		public static IEnumerable<server.Category> ToServerCategories(this IEnumerable<client.Category> categories)
		{
			return categories.Select(c => c.ToServerCategory());
		}

		#endregion

		#region Settings

		public static server.Settings ToServerSettings(this client.Settings settings)
		{
			return new server.Settings()
					   {
                           //UserID = Helpers.CurrentUserHelper.UserID,
                           //FirstName = settings.FirstName,
                           //LastName = settings.LastName,
						   MonthIncome = settings.MonthIncome,
						   MinBalance = settings.MinBalance
					   };
		}

		public static client.Settings ToClientSettings(this server.Settings setting)
		{
			return new client.Settings()
					   {
                           //FirstName = setting.FirstName,
                           //LastName = setting.LastName,
						   MonthIncome = setting.MonthIncome,
						   MinBalance = setting.MinBalance
					   };
		}

		#endregion

		#region Session

		public static client.CurrentUser GetUser(this HttpContext current)
		{
			client.CurrentUser user = null;
			if (current != null)
			{
				user = current.Session["CurrentUser"] as client.CurrentUser;
				if (user == null)
				{
					throw new TypeInitializationException("MCP.Data.Client.CurrentUser", null);
				}
			}

			//return current != null
			//		   ? current.Session["CurrentUser"] as client.CurrentUser
			//		   : null;
			return user;
		}

		////public static void SetUser(this HttpContext current, client.CurrentUser currentUser)
		////{
		////	current.Session["CurrentUser"] = currentUser;
		////}

		////public static void SetUser(this HttpContext current, Guid userID, string username = null, string firstName = null, string lastName = null)
		////{
		////	current.Session["CurrentUser"] = new client.CurrentUser() { UserID = userID, Username = username, FirstName = firstName, LastName = lastName };
		////}

		#endregion

		#region User

		public static client.CurrentUser ToCurrentUser(this server.User user)
		{
			var currentUser = new client.CurrentUser()
			{
				UserID = user.ID,
				Username = user.Username,
				FirstName = string.Empty,
				LastName = string.Empty
			};

			return currentUser;
		}

		public static client.CurrentUser ToCurrentUser(this server.User user, server.Settings userSettings)
		{
			var currentUser = new client.CurrentUser()
											 {
												 UserID = user.ID,
												 Username = user.Username,
                                                 //FirstName = userSettings.FirstName,
                                                 //LastName = userSettings.LastName,

												 MonthIncome = userSettings.MonthIncome,
												 MinBalance = userSettings.MinBalance
											 };

			return currentUser;
		}

		public static CurrentBalanceMessage GetCurrentBalanceStatus(this client.CurrentUser user, IUnitOfWork unitOfWork)
		{
			if (!user.MonthIncome.HasValue) return null;

			double? currentBalance = null;
			double? percent = null;

			var getChecksResult = unitOfWork.CheckRepository.GetChecks();
			if (!getChecksResult.Success) return null;
			
			var monthSpends = (double)getChecksResult.Result
													  .Where(c => c.Date.Month == DateTime.Now.Month)
													  .Sum(c => c.TotalPrice);
			currentBalance = CurrentUserHelper.User.MonthIncome - monthSpends - CurrentUserHelper.User.MinBalance;

			percent = currentBalance / (CurrentUserHelper.User.MonthIncome - CurrentUserHelper.User.MinBalance) * 100;

			var message = new CurrentBalanceMessage();
			message.ComposeMessage(currentBalance, percent);

			return message;
		}

		#endregion
	}
}